﻿using System;
using System.Collections.Generic;
using Office = Microsoft.Office.Core;
using PPT = Microsoft.Office.Interop.PowerPoint;
using System.Xml;
using An_Im.Xml;
using System.Xml.Linq;

namespace An_Im
{
    /// <summary>
    /// 效果列表
    /// </summary>
    internal static class AnimEffect
    {
        #region data set

        /// <summary>
        /// 行为类型->名称
        /// </summary>
        private static Dictionary<PPT.MsoAnimType, string> typedic1;

        /// <summary>
        /// 名称->行为类型
        /// </summary>
        private static Dictionary<string, PPT.MsoAnimType> typedic2;

        /// <summary>
        /// 动画属性->名称
        /// </summary>
        private static Dictionary<PPT.MsoAnimProperty, string> propdic1;

        /// <summary>
        /// 名称->动画属性
        /// </summary>
        private static Dictionary<string, PPT.MsoAnimProperty> propdic2;

        /// <summary>
        /// 动画效果，如《百叶窗》->名称
        /// </summary>
        private static Dictionary<PPT.MsoAnimEffect, Tuple<string, string>> animtypedic1;

        /// <summary>
        /// 名称->动画效果如《百叶窗》
        /// </summary>
        private static Dictionary<string, NativeAnimEffect> animtypedic2;

        /// <summary>
        /// 原生动画列表。
        /// </summary>
        public static IEnumerable<NativeAnimEffect> NativeAnimTypeList => animtypedic2.Values;

        /// <summary>
        /// 动画信息映射表。
        /// </summary>
        public static Dictionary<string, PPT.MsoAnimType> AnimPropertyTypeDictionary => typedic2;

        #endregion

        public static void Initialize()
        {
            typedic1 = CoreManipulator.typedic1;
            typedic2 = CoreManipulator.typedic2;
            propdic1 = CoreManipulator.propdic1;
            propdic2 = CoreManipulator.propdic2;
            animtypedic1 = CoreManipulator.animtypedic1;
            animtypedic2 = CoreManipulator.animtypedic2;
            LoadMsoAnimEffectDic();
            LoadCustomRenamedAnimEffect();
        }

        #region native effect
        private static void AddAnimEffectRecord(PPT.MsoAnimEffect animType, string name)
        {
            animtypedic1.Add(animType, new Tuple<string, string>(name, name));
            animtypedic2.Add(name, new NativeAnimEffect(animType, null) { OriginName = name, ReplacedName = name });
        }

        private static void AddAnimEffectRecord(PPT.MsoAnimEffect animType, string name1, string name2)
        {
            animtypedic1.Add(animType, new Tuple<string, string>(name1, name2));
            animtypedic2.Add(name1, new NativeAnimEffect(animType, Office.MsoTriState.msoFalse) { OriginName = name1, ReplacedName = name1 });
            animtypedic2.Add(name2, new NativeAnimEffect(animType, Office.MsoTriState.msoTrue) { OriginName = name2, ReplacedName = name2 });
        }

        // 加载原数据。
        private static void LoadMsoAnimEffectDic()
        {
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectCustom, "自定义");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectAppear, "出现", "消失");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectFade, "淡入", "淡出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectGrowShrink, "放大缩小");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectSpin, "陀螺旋");

            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectBlinds, "百叶窗进入", "百叶窗退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectWipe, "擦除进入", "擦除退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectFly, "飞入", "飞出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectBox, "盒状进入", "盒状退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectStrips, "阶梯状进入", "阶梯状退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectDiamond, "菱形进入", "菱形退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectWheel, "轮子进入", "轮子退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectSplit, "劈裂进入", "劈裂退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectCheckerboard, "棋盘进入", "棋盘退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPeek, "切入进入", "切入退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPlus, "十字形扩展进入", "十字形扩展退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectRandomBars, "随机线条进入", "随机线条退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectDissolve, "向内溶解进入", "向内溶解退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectWedge, "楔入进入", "楔入退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectCircle, "圆形扩展进入", "圆形扩展退出");
            // AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectFade, "淡化进入", "淡化退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectFadedZoom, "缩放进入", "缩放退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectFadedSwivel, "旋转进入", "旋转退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectExpand, "展开进入", "展开退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectGrowAndTurn, "翻转式由远及近进入", "翻转式由远及近退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectSpinner, "回旋进入", "回旋退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectZoom, "基本缩放进入", "基本缩放退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectAscend, "上浮进入", "上浮退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectStretch, "伸展进入", "伸展退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectRiseUp, "升起进入", "升起退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectDescend, "下浮进入", "下浮退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectStretchy, "压缩进入", "压缩退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectCenterRevolve, "中心旋转进入", "中心旋转退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectBounce, "弹跳进入", "弹跳退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectSwish, "掉落进入", "掉落退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectBoomerang, "飞旋进入", "飞旋退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectFloat, "浮动进入", "浮动退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectWhip, "挥鞭式进入", "挥鞭式退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectSwivel, "基本旋转进入", "基本旋转退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectFlip, "空翻进入", "空翻退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectSpiral, "螺旋飞入", "螺旋飞出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectArcUp, "曲线向上进入", "曲线向上退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPinwheel, "玩具风车进入", "玩具风车退出");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectCredits, "字幕式进入", "字幕式退出");

            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectChangeFillColor, "填充颜色");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectTransparency, "透明");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectChangeLineColor, "线条颜色");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectChangeFontColor, "字体颜色");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectLighten, "变淡");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectComplementaryColor, "补色");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectComplementaryColor2, "补色2");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectDesaturate, "不饱和");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectContrastingColor, "对比色");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectColorBlend, "对象颜色");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectBrushOnColor, "画笔颜色");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectBoldFlash, "加粗闪烁");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectDarken, "加深");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectFlashBulb, "脉冲");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectBrushOnUnderline, "下划线");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectFlicker, "彩色脉冲");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectGrowWithColor, "彩色延伸");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectTeeter, "跷跷板");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectShimmer, "闪现");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectWave, "波浪形翻动");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectBoldReveal, "加粗展示");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathOctagon, "八边形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPath8PointStar, "八角星");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathEqualTriangle, "等边三角形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathFootball, "橄榄球形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathTeardrop, "泪滴形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathDiamond, "菱形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathHexagon, "六边形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPath6PointStar, "六角星");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathParallelogram, "平行四边形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPath4PointStar, "四角星");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathTrapezoid, "梯形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathPentagon, "五边形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPath5PointStar, "五角星");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathHeart, "心形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathCrescentMoon, "新月形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathCircle, "圆形扩展");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathSquare, "正方形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathRightTriangle, "直角三角形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathSCurve1, "S 形曲线 1");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathSCurve2, "S 形曲线 2");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathWave, "波浪形曲线");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathSpring, "弹簧");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathDiagonalUpRight, "对角线向右上");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathDiagonalDownRight, "对角线向右下");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathFunnel, "漏斗");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathSpiralRight, "螺旋向右");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathSpiralLeft, "螺旋向左");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathDecayingWave, "衰减波");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathZigzag, "弯弯曲曲");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathUp, "向上");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathArcUp, "向上弧线");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathTurnUp, "向上转");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathDown, "向下");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathArcDown, "向下弧线");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathStairsDown, "向下阶梯");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathTurnDown, "向下转");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathRight, "向右");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathBounceRight, "向右弹跳");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathArcRight, "向右弧线");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathTurnUpRight, "向右上转");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathCurvyRight, "向右弯曲");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathTurnRight, "向右下转");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathLeft, "向左");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathBounceLeft, "向左弹跳");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathArcLeft, "向左弧线");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathCurvyLeft, "向左弯曲");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathHeartbeat, "心跳");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathSineWave, "正弦波");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathVerticalFigure8, "垂直数字 8");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathBean, "豆荚");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathPeanut, "花生");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathPointyStar, "尖角星");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathLoopdeLoop, "涟漪");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathSwoosh, "飘扬形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathInvertedTriangle, "三角结");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathPlus, "十字形扩展");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathFigure8Four, "双八串接");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathHorizontalFigure8, "水平数字 8");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathCurvedX, "弯曲的 X");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathCurvyStar, "弯曲的星形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathCurvedSquare, "圆角正方形");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathInvertedSquare, "正方形结");
            AddAnimEffectRecord(PPT.MsoAnimEffect.msoAnimEffectPathNeutron, "中子");

        }

        // 在原基础上加载重命名数据。
        private static void LoadCustomRenamedAnimEffect()
        {
            var path = CoreManipulator.RenamedAnimationEffectConfigPath;
            var hasPath = System.IO.File.Exists(path);
            if (hasPath)
            {
                var xmldoc = new XmlDocument();
                xmldoc.Load(path);
                var root = xmldoc.DocumentElement;

                foreach (XmlElement xmlnode in root.ChildNodes)
                {
                    var sysName = xmlnode.GetAttribute("SystemName");
                    var repName = xmlnode.GetAttribute("ReplacedName");
                    if (animtypedic2.ContainsKey(sysName))
                    {
                        animtypedic2[sysName].ReplacedName = repName;
                    }
                }
            }

        }

        // 从效果中直接提取原生信息。
        public static NativeAnimEffect GetNativeAnimEffect(PPT.Effect eff)
        {
            var type = GetAnimEffect(eff);

            if (!animtypedic1.ContainsKey(type)) return null;

            var namepair = animtypedic1[type];
            var name = namepair.Item1;
            if (IsEntryExitAnimEffect(type) && eff.Exit == Office.MsoTriState.msoTrue)
            {
                name = namepair.Item2;
            }
            if (!animtypedic2.ContainsKey(name)) return null;
            return animtypedic2[name];
        }

        // 是否为进入或退出动画
        private static bool IsEntryExitAnimEffect(PPT.MsoAnimEffect type)
        {
            if ((int)type == 52 || (int)type >= 54 || type == PPT.MsoAnimEffect.msoAnimEffectCustom)
                return false;
            else
                return true;
        }

        // 合法地获得动画效果（因为有些类型不允许读取）。
        private static PPT.MsoAnimEffect GetAnimEffect(PPT.Effect eff)
        {
            try
            {
                return eff.EffectType;
            }
            catch
            {
                return PPT.MsoAnimEffect.msoAnimEffectGrowShrink;
            }


        }


        /// <summary>
        /// 保存自定义重命名动画配置文件。
        /// </summary>
        public static void SaveCustomRenamedAnimEffect()
        {
            var path = CoreManipulator.RenamedAnimationEffectConfigPath;
            var xmldoc = new XmlDocument();
            var root = xmldoc.CreateElement("RenameAnimationEffectRoot");

            foreach (var eff in animtypedic2.Values)
            {
                var node = xmldoc.CreateElement("AnimEffect");
                var sysname = xmldoc.CreateAttribute("SystemName");
                sysname.Value = eff.OriginName;
                var repname = xmldoc.CreateAttribute("ReplacedName");
                repname.Value = eff.ReplacedName;
                node.Attributes.Append(sysname);
                node.Attributes.Append(repname);
                root.AppendChild(node);
            }


            xmldoc.AppendChild(root);
            xmldoc.Save(path);


        }

        #endregion


        #region property type

        /// <summary>
        /// 通过查询名称获得动画类型属性。
        /// </summary>
        public static PPT.MsoAnimProperty GetPropertyTypeFromName(string name)
        {
            if (propdic2.ContainsKey(name))
                return propdic2[name];
            else
                return PPT.MsoAnimProperty.msoAnimNone;
        }

        /// <summary>
        /// 通过查询动画类型属性类型获得属性名称。
        /// </summary>
        public static string GetPropertyNameFromMsoAnimProperty(PPT.MsoAnimProperty animtype)
        {
            if (propdic1.ContainsKey(animtype))
                return propdic1[animtype];
            else
                return "未知";
        }

        public static IEnumerable<string> GetAvaliableAnimPropertyTypeList()
        {
            var list = new List<string>();
            list.Add(propdic1[PPT.MsoAnimProperty.msoAnimVisibility]);
            list.Add(propdic1[PPT.MsoAnimProperty.msoAnimX]);
            list.Add(propdic1[PPT.MsoAnimProperty.msoAnimY]);
            list.Add(propdic1[PPT.MsoAnimProperty.msoAnimWidth]);
            list.Add(propdic1[PPT.MsoAnimProperty.msoAnimHeight]);
            list.Add(propdic1[PPT.MsoAnimProperty.msoAnimRotation]);
            list.Add(propdic1[PPT.MsoAnimProperty.msoAnimOpacity]);
            return list;
        }

        #endregion

    }
}
